package com.godenwater.recv.server.all;

import com.godenwater.recv.model.CommonMessage;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;


import cn.gov.mwr.sl651.Symbol;
import cn.gov.mwr.sl651.utils.ByteUtil;

public class ClientDataDecoder implements ProtocolDecoder {
	private static final AttributeKey BUF_BYTE = new AttributeKey(
			ClientDataDecoder.class, "BUF_KEY");

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
			throws Exception {
		// TODO Auto-generated method stub
		try {

			System.out.println(">>> ClientDataDecoder decode "
					+ StringUtils.trimAllWhitespace(in.getHexDump()));

			IoBuffer buffer = null;
			byte[] buf = (byte[]) session.getAttribute(BUF_BYTE);
			if (buf == null) {
				// System.out.println("没有尚未处理的数据");
				buffer = in;
			} else {
				// System.out.println("合并尚未处理的数据");
				buffer = IoBuffer.allocate(buf.length + in.remaining());
				buffer.setAutoExpand(true);
				buffer.put(buf);
				buffer.put(in);
				buffer.flip();
			}

			// while (buffer.remaining() >= 0) {// 循环处理数据包
			// //
			// int dataLen = buffer.getInt(buffer.position());
			// byte[] b = new byte[dataLen];
			// buffer.get(b);
			// SMPPPacket pak = null;
			// int id = -1;
			// id = SMPPIO.bytesToInt(b, 4, 4);
			// pak = PacketFactory.newInstance(id);
			// if (pak != null) {
			// pak.readFrom(b, 0);
			// out.write(pak);
			// }

			CommonMessage temp = null;

			byte[] mode = new byte[1];
			buffer.get(mode);

			if (mode[0] == (byte) Symbol.SOH_ASC) {
				// 1、表示是水文的ASC码协议
				temp = decodeSl651(buffer);
			} else if (mode[0] == (byte) Symbol.SOH_HEX) {
				// 2、表示是水文的HEX码协议
				byte[] secondBit = new byte[1];
				buffer.get(secondBit);

				// 表示是7474，水文的16进制报文数据
				if (secondBit[0] == (byte) Symbol.SOH_HEX) {
					temp = decodeSl651(buffer);
				} else {
					// 不能使用74做为中心站名
					temp = decodeYanyu(buffer, secondBit);
				}

			} else if (mode[0] == (byte) 0x68) {
				// 水资源协议
				decodeSzy206(buffer);

			} else {
				// 处理DTU设备上线时的登录信息，发的是DTU编号和手机号
				// buffer.get(buffer.array().length);
				logger.info(">> 非协议报文 ");
				byte[] remain = new byte[buffer.remaining()];
				buffer.get(remain);
				return ;
			}

			// ---------------------------------------------
			// 转换报文中的上下行标识及报文长度
			byte[] bodyContent = new byte[temp.getBodySize ()];// 根据前面header的内容来获取长度
			buffer.get(bodyContent);

			// // 终止符
			byte[] eof = new byte[1];
			// buffer.get(eof);

			// 校验码
			byte[] crc = new byte[temp.getCrclen()];

			// 两种协议的CRC校验符与结束符，正好相反
			if (mode[0] == (byte) 0x68) {
				// 水资源协议
				buffer.get(crc);
				buffer.get(eof);
			} else {
				// 水文协议
				buffer.get(eof);
				buffer.get(crc);
			}

			// 组装消息
			CommonMessage message = new CommonMessage();
			message.setHeader(temp.getHeader());
			message.setContents(bodyContent);
			message.setEOF(eof[0]);
			message.setCRC(crc);

			out.write(message);

			// }
			if (buffer.hasRemaining()) {// 如果有剩余的数据，则放入Session中
				byte[] tmpb = new byte[buffer.remaining()];
				buffer.get(tmpb);
				session.setAttribute(BUF_BYTE, tmpb);
			}

		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	private int parseLength(byte[] bodyLen) {
		byte A1 = (byte) (bodyLen[0] & 0x0f);
		byte A2 = bodyLen[1];
		return ByteUtil.bytesToUshort(new byte[] { A1, A2 });
	}

	public void dispose(IoSession session) throws Exception {
		// TODO Auto-generated method stub

	}

	public void finishDecode(IoSession session, ProtocolDecoderOutput out)
			throws Exception {
		// TODO Auto-generated method stub

	}

	public CommonMessage decodeSl651(IoBuffer buffer) {
		cn.gov.mwr.sl651.header.HexHeader header = new cn.gov.mwr.sl651.header.HexHeader();

		header.setStartBit(new byte[] { Symbol.SOH_HEX, Symbol.SOH_HEX });

		// 下行的，遥测站地址在前
		byte[] stationAddr = new byte[header.getStationAddrLen()];
		buffer.get(stationAddr);
		header.setStationAddr(stationAddr);

		// 下行的，中心站地址在后
		byte[] centerAddr = new byte[header.getCenterAddrLen()];
		buffer.get(centerAddr);
		header.setCenterAddr(centerAddr);

		// 解析密码
		byte[] password = new byte[header.getPasswordLen()];
		buffer.get(password);
		header.setPassword(password);

		// 解析 功能码
		byte[] funcCode = new byte[header.getFuncCodeLen()];
		buffer.get(funcCode);
		header.setFuncCode(funcCode);

		// 解析报文上行标识及消息体长度
		byte[] BodySize = new byte[header.getBodySizeLen()];
		buffer.get(BodySize);
		header.setBodySize(BodySize);

		// 解析消息开始体
		byte[] bodyStartBit = new byte[header.getBodyStartBitLen()];
		buffer.get(bodyStartBit);
		header.setBodyStartBit(bodyStartBit);

		// 如果是SYN，表示是多包发送。多包发送，一次确认的传输模式中使用
		if (bodyStartBit[0] == Symbol.SYN) {
			byte[] bodyCount = new byte[header.getBodyCountLen()];
			buffer.get(bodyCount);
			header.setBodyCount(bodyCount);
		}

		// 转换报文中的上下行标识及报文长度
		int bodySizeLen = parseLength(BodySize);// 需要考虑拆分字节;
		if (bodyStartBit[0] == Symbol.SYN) {
			bodySizeLen = bodySizeLen - header.getBodyCountLen();
		}
		int crclen = 2;

		// --------------------------------
		CommonMessage temp = new CommonMessage();
		temp.setHeader(header);
		temp.setCrclen(crclen);
		temp.setBodySize(bodySizeLen);

		return temp;
	}

	public void decodeSzy206(IoBuffer buffer) {

	}

	public CommonMessage decodeYanyu(IoBuffer buffer, byte[] secondBit) {
		// 燕禹协议
		com.godenwater.yanyu.YYMessageHeader header = new com.godenwater.yanyu.YYMessageHeader();

		// 7E 目的地址 源地址 特征 长度 时间1《数据》 ETX CRC16H CRC16L
		header.setStartBit(new byte[] { Symbol.SOH_HEX });

		//  测站地址
		header.setStationAddr(secondBit);

		// 上行的，中心站地址在前
		byte[] centerAddr = new byte[header.getCenterAddrLen()];
		buffer.get(centerAddr);
		header.setCenterAddr(centerAddr);

		// 特征码
		byte[] funccode = new byte[header.getFuncCodeLen()];
		buffer.get(funccode);
		header.setFuncCode(funccode);

		// 报文长度
		byte[] bodySize = new byte[header.getBodySizeLen()];
		buffer.get(bodySize);
		header.setBodySize(bodySize);

		// 转换报文中的上下行标识及报文长度
		int bodySizeLen = ByteUtil.bytesToUbyte(bodySize);// 需要考虑拆分字节;

		int crclen = 2;

		// --------------------------------
		CommonMessage temp = new CommonMessage();
		temp.setHeader(header);
		temp.setCrclen(crclen);
		temp.setBodySize(bodySizeLen - 3);

		return temp;
	}

	 

}
